// EEC.cpp: 定义控制台应用程序的入口点。
//

#include "EntityState.h"
#include <chrono>
#include <iostream>

//使用例子
struct complex 
{
  ~complex() {}
};
using name = const char *; //一个名字状态,任何类型都可以成为状态
using number = size_t;     //整数状态
struct position 
{
  float x, y;
}; //一个具名结构体状态
struct room 
{
  using state_type = EntityState::global_state; //指定状态为全局状态
  const char *name;
};


void entity_state_example() 
{
  using World = EntityState::StateManager<name, position, room>; //创建一个管理器
  World manager;
  // game.ref<room>().name = "bedroom";
  manager.transit([](room &r) { r.name = "bedroom"; }); //索引全局状态
  {
    auto e = manager.create_entity(); //创建一个实体
	e.add(name{ "Jack" });                    //添加状态,带构造参数
	e.add(position{ 1.f, 1.f });
  }
  {
    auto e = manager.create_entity();
    e.add<name>("Julia");
    e.add<position>(7.f, 1.f);
  }
  auto whos_in = [](name &n, position &pos, room &r) 
  {
    std::cout << n << " is in " << r.name << " at: (" << pos.x << "," << pos.y
              << ");\n";
  };
  manager->*whos_in;
}

class TimerBlock 
{
  std::chrono::high_resolution_clock::time_point start;
  const char *str;

public:
  TimerBlock(const char *str)
      : start(std::chrono::high_resolution_clock::now()), str(str) 
  {
    std::cout << str << " start... \n";
  }
  ~TimerBlock() 
  {
    auto end = std::chrono::high_resolution_clock::now();
    std::cout << str << " finished, time used: "
              << std::chrono::duration_cast<std::chrono::milliseconds>(end -
                                                                       start)
                     .count()
              << "ms\n\n";
  }
};

struct location 
{
  int x, y;
};

struct velocity 
{
  int x, y;
};

void performance_example() 
{
  using namespace EntityState;
  using States = StateManager<location, velocity>; 
  States states;
  {
    TimerBlock timer("create 10m entity");
    for (size_t i{1u}; i <= 10'000'000u; i++) 
    {
      auto e = states.create_entity();
      e.add(location{0, 0});
      e.add(velocity{0, 0});
    }
  }
  auto move = [](location &pos, velocity &vel)
  {
	  pos.x += vel.x;
	  pos.y += vel.y;
  };
  {
    TimerBlock timer("transit");
    states->*move;
  }
}

int _cdecl main() {
  performance_example();
  getchar();
  return 0;
}
